package com.domainlanguage.time;

import com.domainlanguage.time.CalendarDate;
import org.hibernate.HibernateException;
import org.hibernate.type.ImmutableType;

import java.sql.*;
import java.util.Calendar;

/**
 * Hibernate user type for {@link com.domainlanguage.time.CalendarDate}.
 *
 * Backed by SQL {@link java.sql.Types.DATE}.
 *
 */
public class CalendarDateType extends ImmutableType {

    private static final String PATTERN = "yyyy-MM-dd";

    @Override
    public Object get(ResultSet rs, String name) throws HibernateException, SQLException {
        final Date sqlDate = rs.getDate(name);
        if (sqlDate == null) {
            return null;
        }
        
        final Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(sqlDate.getTime());

        return CalendarDate.from(
                calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH) + 1,
                calendar.get(Calendar.DAY_OF_MONTH)
        );
    }

    @Override
    public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        final CalendarDate calendarDate = (CalendarDate) value;
        final Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, calendarDate.breachEncapsulationOf_year());
        calendar.set(Calendar.MONTH, calendarDate.breachEncapsulationOf_month() - 1);
        calendar.set(Calendar.DAY_OF_MONTH, calendarDate.breachEncapsulationOf_day());
        // Zero out hour and down
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        final Date sqlDate = new Date(calendar.getTimeInMillis());

        st.setDate(index, sqlDate);
    }

    @Override
    public int sqlType() {
        return Types.DATE;
    }

    @Override
    public String toString(Object value) throws HibernateException {
        final CalendarDate calendarDate = (CalendarDate) value;
        return calendarDate.toString(PATTERN);
    }

    @Override
    public Object fromStringValue(String xml) throws HibernateException {
        return CalendarDate.from(xml, PATTERN);
    }

    @Override
    public Class getReturnedClass() {
        return CalendarDateType.class;
    }

    @Override
    public String getName() {
        return "calendarDate";
    }

}
